package com.ruoyi.teaching.service.impl;



import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;


import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.teaching.domain.*;
import com.ruoyi.teaching.domain.vo.InsertTeachingPlan;
import com.ruoyi.teaching.domain.vo.PreviewTeachingPlan;
import com.ruoyi.teaching.domain.vo.RelatedInterviewVo;
import com.ruoyi.teaching.es.TeachingPlanStudent;
import com.ruoyi.teaching.mapper.ClassesMapper;
import com.ruoyi.teaching.mapper.CourseDesignMapper;
import com.ruoyi.teaching.mapper.HolidayMapper;
import com.ruoyi.teaching.util.IKAnalyzerUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.teaching.mapper.TeachingPlanMapper;
import com.ruoyi.teaching.service.ITeachingPlanService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 教学计划Service业务层处理
 *
 * @author sunshine
 * @date 2024-01-30
 */
@Service
public class TeachingPlanServiceImpl implements ITeachingPlanService
{
    public static final String CLASSES_XXDAY = "classes:xxday:";
    public static final String CLASSES_SELFDAY = "classes:selfday:";
    public static final String CLASSES_WORKDAY = "classes:workday:";
    public static final String XX = "休息";
    public static final String selfday = "自习";
    public static final String TRUE = "true";
    @Autowired
    private TeachingPlanMapper teachingPlanMapper;
    @Autowired
    private ClassesMapper classesMapper;
    @Autowired
    private CourseDesignMapper courseDesignMapper;
    @Autowired
    private HolidayMapper holidayMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 查询教学计划
     *
     * @param id 教学计划主键
     * @return 教学计划
     */
    @Override
    public TeachingPlan selectTeachingPlanById(Long id)
    {
        return teachingPlanMapper.selectTeachingPlanById(id);
    }

    /**
     * 查询教学计划列表
     *
     * @param teachingPlan 教学计划
     * @return 教学计划
     */
    @Override
    public List<TeachingPlan> selectTeachingPlanList(TeachingPlan teachingPlan)
    {
        return teachingPlanMapper.selectTeachingPlanList(teachingPlan);
    }

    /**
     * 新增教学计划
     *
     * @param teachingPlan 教学计划
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTeachingPlan(InsertTeachingPlan teachingPlanList)
    {

        if(ObjectUtils.isEmpty(teachingPlanList)){
            throw new ServiceException("教学计划不能为空");
        }
        List<TeachingPlan> teachingPlanList1 = teachingPlanList.getTeachingPlanList();
        TeachingPlan plan1 = teachingPlanList1.get(1);
        Integer stage = plan1.getStage();
        teachingPlanMapper.deleteTeachingPlan(stage);
        TeachingPlan teachingPlan = new TeachingPlan();

        for (TeachingPlan plan:teachingPlanList1){
            teachingPlan.setDate(plan.getDate());
            teachingPlan.setCourseContent(plan.getCourseContent());
            teachingPlan.setClassName(plan.getClassName());
            teachingPlan.setStage(plan.getStage());
            teachingPlan.setRemarks(plan.getRemarks());
            teachingPlan.setWeekday(plan.getWeekday());
            teachingPlan.setClassesId(plan.getClassesId());
            teachingPlan.setCourseDesignId(plan.getCourseDesignId());
            teachingPlan.setDay(plan.getDay());
            teachingPlanMapper.insertTeachingPlan(teachingPlan);
        }


        List<TeachingPlan> teachingPlans = teachingPlanMapper.selectTeachingPlanList(null);
//        先同步给es
//        将teachingPlans转为TeachingPlanStudent
        List<TeachingPlanStudent> collect = teachingPlans.stream().map(te -> {
            TeachingPlanStudent build = TeachingPlanStudent.builder().courseContent(te.getCourseContent()).build();
//                通过反射工具自动将teachingPlans中的字段拷贝给TeachingPlanStudent
            BeanUtils.copyBeanProp(build, te);
            return build;
        }).collect(Collectors.toList());
        elasticsearchRestTemplate.save(collect);
//

        return 0;
    }

    /**
     * 修改教学计划
     *
     * @param teachingPlan 教学计划
     * @return 结果
     */
    @Override
    public int updateTeachingPlan(TeachingPlan teachingPlan)
    {
        return teachingPlanMapper.updateTeachingPlan(teachingPlan);
    }

    /**
     * 批量删除教学计划
     *
     * @param ids 需要删除的教学计划主键
     * @return 结果
     */
    @Override
    public int deleteTeachingPlanByIds(Long[] ids)
    {
        return teachingPlanMapper.deleteTeachingPlanByIds(ids);
    }

    /**
     * 删除教学计划信息
     *
     * @param id 教学计划主键
     * @return 结果
     */
    @Override
    public int deleteTeachingPlanById(Long id)
    {
        return teachingPlanMapper.deleteTeachingPlanById(id);
    }

    @Override
    public List<TeachingPlan> previewTeachingPlanList(PreviewTeachingPlan previewTeachingPlan) {
//        1.获取班级的休息日或者自习日
        Classes classes = classesMapper.selectOne(new LambdaQueryWrapper<Classes>().eq(Classes::getClassName,previewTeachingPlan.getClassName()));
//        2.判断班级是否为空
        if (ObjectUtils.isEmpty(classes)){
            throw new ServiceException("班级为空");
        }
        Long classesId = classes.getId();
        Integer restDay = classes.getRestDay();
        Integer selfStudyDay = classes.getSelfStudyDay();
//        查询该阶段对应课程设计列表
        List<CourseDesign> courseDesigns = courseDesignMapper.selectList(new LambdaQueryWrapper<CourseDesign>().eq(CourseDesign::getStage,previewTeachingPlan.getStage()));
//        查询起始年份
        Map<String,String> selectDate = holidayMapper.selectDate(previewTeachingPlan.getBeginDate()).stream().collect(Collectors.toMap(Holiday::getDate,Holiday::getDescription));
        Map<Object, Object> reset = stringRedisTemplate.opsForHash().entries(CLASSES_XXDAY + classesId);
        Map<Object, Object> selfday = stringRedisTemplate.opsForHash().entries(CLASSES_SELFDAY + classesId);
        Map<Object, Object> workday = stringRedisTemplate.opsForHash().entries(CLASSES_WORKDAY + classesId);

//        5.创建预览课表
        String beginDate2 = previewTeachingPlan.getBeginDate();
        LocalDate beginDate = LocalDate.parse(beginDate2);
        ArrayList<TeachingPlan> teachingPlans = new ArrayList<>();
        int day = 1;
        do{
            String beginDate1 = beginDate.toString();
            int weekday = beginDate.getDayOfWeek().getValue();
            TeachingPlan teachingPlan = new TeachingPlan();
            teachingPlan.setWeekday(weekday);
            teachingPlan.setClassName(classes.getClassName());
            teachingPlan.setClassesId(classes.getId());
            teachingPlan.setDate(beginDate1);
            teachingPlan.setStage(previewTeachingPlan.getStage());
//            判断是否为国家法定节假日

            if (selectDate.containsKey(beginDate1)){
                teachingPlan.setCourseContent(selectDate.get(beginDate1));
            }
//          判断
            else if (reset.containsKey(beginDate1)){
                teachingPlan.setCourseContent(reset.get(beginDate1).toString());
            }
            else if (selfday.containsKey(beginDate1)){
                teachingPlan.setCourseContent(selfday.get(beginDate1).toString());
            }
            else if (workday.containsKey(beginDate1)){
                teachingPlan.setCourseContent(workday.get(beginDate1).toString());
            }
            else if(restDay.equals(weekday) && !workday.containsKey(beginDate1)){
                teachingPlan.setCourseContent("休息");
            }
            else if(selfStudyDay.equals(weekday) && !workday.containsKey(beginDate1)){
                teachingPlan.setCourseContent("自习");
            }
            else {
                CourseDesign courseDesign = courseDesigns.get(day - 1);
                teachingPlan.setCourseContent(courseDesign.getCourseContent());
                teachingPlan.setDay((long)day);
                teachingPlan.setCourseDesignId(courseDesign.getCourseId());
                day++;
            }
            beginDate = beginDate.plusDays(1);
            teachingPlans.add(teachingPlan);
        }while (day-1 < courseDesigns.size());

        return teachingPlans;

    }

    @Override
    public void addWorkday(String classesId, String date) {
        stringRedisTemplate.opsForHash().put(CLASSES_WORKDAY+classesId,date,"特殊上课日");
        stringRedisTemplate.opsForHash().delete(CLASSES_SELFDAY+classesId,date);
        stringRedisTemplate.opsForHash().delete(CLASSES_XXDAY+classesId,date);

    }

    @Override
    public void addHoliday(String classesId, String date, String type) {
        if (XX.equals(type)){
            stringRedisTemplate.opsForHash().put(CLASSES_XXDAY+classesId,date,"特殊休息日");
            stringRedisTemplate.opsForHash().delete(CLASSES_WORKDAY+classesId,date);
            stringRedisTemplate.opsForHash().delete(CLASSES_SELFDAY+classesId,date);
        }
        if (selfday.equals(type)){
            stringRedisTemplate.opsForHash().put(CLASSES_SELFDAY+classesId,date,"特殊自习日");
            stringRedisTemplate.opsForHash().delete(CLASSES_XXDAY+classesId,date);
            stringRedisTemplate.opsForHash().delete(CLASSES_WORKDAY+classesId,date);

        }

    }

    @Override
    public RelatedInterviewVo selectTeachingPlanByStudentList(TeachingPlan teachingPlan) {
        RelatedInterviewVo result = new RelatedInterviewVo();
        if (ObjectUtils.isEmpty(teachingPlan.getStage())){
            List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectTeachingPlanList(null);;
            result.setTeachingPlanList(teachingPlanList);
            return result;
        }

//        根据cdid查询相关面试题
        String courseContent = teachingPlan.getCourseContent();
//long->Long
        if (TRUE.equals(teachingPlan.getDate()) || teachingPlan.getDay() == 0){
            if (TRUE.equals(teachingPlan.getDate()) ){
                String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
                List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectTeachingByDate(format);;
                result.setTeachingPlanList(teachingPlanList);
                return result;
            }
            if (teachingPlan.getDay() == 0){
                List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectTeachingByDay();;
                result.setTeachingPlanList(teachingPlanList);
                return result;
            }
            String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectTeachingByDayOrDate(format);;
            result.setTeachingPlanList(teachingPlanList);
            return result;
        }

        Integer stage = teachingPlan.getStage();

        List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectTeachingPlanByStage(stage);
        Set<String> keywords = IKAnalyzerUtils.parseSentence(courseContent);
        if (CollectionUtils.isEmpty(keywords)){
            result.setTeachingPlanList(teachingPlanList);
            return result;
        }
        result.setKeywords(keywords);


//        if (CollectionUtils.isNotEmpty(teachingPlanList)){
//            result.setTeachingPlanList(teachingPlanList);
//            result.setRelatedInterviewIdList(teachingPlanList.stream().map(TeachingPlan::getId).collect(Collectors.toList()));
//            return result;
//        }

//        es
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        添加查询条件
        boolQueryBuilder.must(QueryBuilders.matchQuery("courseContent",courseContent));
//        过滤
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0,100));
            SearchHits<TeachingPlanStudent> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), TeachingPlanStudent.class);
//        将SearchHits<InterviewIndex>对象转换成面试题集合
            List<TeachingPlan> collect = search.getSearchHits().stream().map(sear -> {
                TeachingPlanStudent content = sear.getContent();
                TeachingPlan plan = new TeachingPlan();
                BeanUtils.copyBeanProp(plan, content);
                return plan;
            }).collect(Collectors.toList());

            result.setTeachingPlanList(collect);


        return result;
    }
}
